import Ajv from 'ajv';
import { SwaggerJson } from 'auto-service/lib/consts';
import { SwaggerLikeJson } from 'auto-service/lib/yapi/yapiJSon2swagger';
import swaggerJsonAr from '../../services/swagger-file/ar.raw.swagger.json';
import swaggerJsonQuest from '../../services/swagger-file/quest.raw.swagger.json';
import { AnyObject } from '../types';
import { ApiServiceName } from './service-name';

/**
 * 处理一下对definitions的引用，让ajv能识别
 * @param schema
 * @returns
 */
const formatSchema = <S>(schema: S) =>
  JSON.parse(
    JSON.stringify(schema).replace(
      /"#\/definitions/g,
      '"definitions#/definitions',
    ),
  );

/**
 * 获取 swagger json
 * @param type
 * @returns
 */
const getSwaggerJson = (type: ApiServiceName): SwaggerLikeJson => {
  switch (type) {
    case 'ar':
      return swaggerJsonAr as any;
    case 'quest':
      return swaggerJsonQuest as any;
    default:
      throw new Error(`invalid api service name: ${type}`);
  }
};

/**
 * convert url to operation id
 * @param url
 * @param method
 * @returns
 */
const url2OperationId = (url: string, method: 'get' | 'post'): string => {
  let operationId = (url + '/' + method)
    .split('/')
    .map((s) => {
      const regex1 = /^\{(.+?)\}?$/g;
      s = s.replace(regex1, '$1');

      if (s.length > 0) {
        return s.charAt(0).toUpperCase() + s.substring(1);
      }
      return s;
    })
    .join('');
  operationId = operationId.charAt(0).toLowerCase() + operationId.substring(1);

  return operationId;
};

/**
 * 获取 swagger schema
 * @returns
 */
const createSwaggerSchemas = (type: ApiServiceName): SwaggerJson => {
  const schemas = {} as AnyObject;

  const swaggerJson = getSwaggerJson(type);
  for (const [path, pathConfig] of Object.entries(swaggerJson.paths)) {
    if (pathConfig.get) {
      const operationId = url2OperationId(path, 'get');
      schemas[operationId] = pathConfig.get.responses['200'].schema;
    }
    if (pathConfig.post) {
      const operationId = url2OperationId(path, 'post');
      schemas[operationId] = pathConfig.post.responses['200'].schema;
    }
  }

  schemas.definitions = swaggerJson.definitions;

  // console.log(schemas);
  return formatSchema(schemas);
};
const schemasMap = {
  ar: createSwaggerSchemas('ar'),
  quest: createSwaggerSchemas('quest'),
};

/**
 * 将 swagger schema 转成 ajv
 */
export const createAJV = (swagger: SwaggerJson): Ajv.Ajv => {
  const ajv = new Ajv();

  // 对 int32 做特殊处理
  ajv.addFormat('int32', (d: string) => {
    return /^[+-]?\d+$/.test(d);
  });

  // 添加 definitions 处理
  const { definitions } = swagger;
  if (definitions) {
    ajv.addSchema({
      $id: 'definitions',
      definitions: formatSchema(definitions),
    });
  }

  return ajv;
};

const ajvMap = {
  ar: createAJV(schemasMap.ar),
};

export const validataResponse = (
  serviceName: ApiServiceName,
  operationId: string,
  data: unknown,
): void => {
  const schema = schemasMap[serviceName][operationId];
  const ajv = ajvMap[serviceName];
  // eslint-disable-next-line @typescript-eslint/ban-types
  // const result = ajv.validate(schema as object, data);
  // if (!result) {
  //   const errMsg = ajv.errorsText();
  //   throw new Error(errMsg);
  // }
};
